import numpy,defacing,sys,cv
from nifti import NiftiImage
import GaborMatching as gm
import VolRender_np as vr
import threading,subprocess
from optparse import OptionParser
import scipy.ndimage as ndi
import json
import os
import cPickle
import numpy as np


def CreateDepthMap(img_data,data_set,thres):

    return defacing.FrontOrthoRayCast(img_data,thres,data_set)

def getParser():
    try:
        parser = OptionParser()
        parser.add_option("-f", "--filename",dest= "filename",type = "string", default="")
        parser.add_option("-t", "--threshold", dest = "threshold",type = "int",default= 0)
        parser.add_option("-m","--mode",  dest= "mode", type = "string",default= "")
        parser.add_option("-l", "--level", dest= "level", type = "float", default = 0.0)
        parser.add_option("-c", "--command", dest = "command", type = "string", default ="")
        
        return parser

    except Exception, error:
        print "failed to generate parser", error
        sys.exit(0)

def CallDefacer(target):
    print 'Executing Defacer'
    
    tmp = os.path.splitext(target)
    cmd = "mri_deface %s /usr/local/data/Defacer/talairach_mixed_with_skull.gca /usr/local/data/Defacer/face.gca %s"%(target,tmp[0]+"_full_deface"+tmp[1])
    #print cmd
    output = subprocess.call(cmd,shell=True)
    #args[1] =  target
    #args[4] =  tmp[0]+"_full_deface"+tmp[1]
    #print "saving defaced image to",args[4]
    #popen = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
    #popen.wait()
    #output = popen.stdout.read()
    print output
    print 'Finished Execution of Defacer'

def LocateFeatures(data,thres,mode):
    #try:
    nim = NiftiImage( data)
    img_data = nim.data
    thres = int(thres)
    img_data[img_data<thres]=0	
    #vr.show(img_data,thres)
    
    
    img,kmax,max_loc = CreateDepthMap(img_data,data,thres)
    im3 = cv.CloneImage(img)			
    cv.Circle(im3,max_loc,2,(255,0,0))
    
    #cv.ShowImage('result',im3)
        
    #cv.ShowImage('result',img)
    #cv.WaitKey(0)
    if(mode == 'nn'):
        features = gm.matchTheSmartWay2(img,'data/features.data',max_loc)
    elif(mode == 'nnpca'):
        features = gm.matchTheSmartWayPCA(img,'data/features.data',max_loc)
    else:
        features = gm.matchNaive2(img,'data/features.data')
    img2 = img
    for m in range(len(features)):
        cv.Circle(img2,features[m],3,(255,0,0),thickness=-1)
    cv.ShowImage('result',img2)
    tmp = os.path.splitext(data)
    cv.SaveImage(tmp[0]+"_matched_features"+".png",img2)
    
    cv.WaitKey(0)

	#t.join()
def save_model_as_ply(fname,thres,level):
    nim = NiftiImage( fname)
    img_data = nim.data
    thres = int(thres)
    img_data[img_data<thres]=0	
    vr.save_show(img_data,thres,float(level),fname)
            

def RemoveFeatures(data,thres,mode):
    #try:
            
    nim = NiftiImage( data)
    orig_img = nim.data
    thres = int(thres)
    #vr.show(img_data,thres)
    tmp = os.path.splitext(data)
    nim = NiftiImage(tmp[0]+'_defaced'+tmp[1])
    defaced_img = nim.data 	

    #vr.show(defaced_img-img_data,0)
    print  'nasd'
    img,kmax,img_loc = CreateDepthMap(orig_img,data,thres)
    
    #cv.ShowImage('result',img)
    #cv.WaitKey(0)
    if(mode == 'nn'):
        features = gm.matchTheSmartWay2(img,'data/features.data',img_loc)
    elif(mode == 'nnpca'):
        features = gm.matchTheSmartWayPCA(img,'data/features.data',img_loc)
    else:
        features = gm.matchNaive2(img,'data/features.data',img_loc)
    img2 = img
    for m in range(len(features)):
        cv.Circle(img2,features[m],2,(255,0,0))
    cv.ShowImage('result',img2)

    radius = 20 # Costas originally had 40
    dx = radius
    dy = radius

    face_data = orig_img-defaced_img
    face_data_2 =face_data.copy()
    for m in range(len(features)):
        # img is the depth map created from the original data. I wonder if we shouldn't use
        # a depth map created from the face data and use this as the stopper for the image
        # I think this could be simplified by sticking with numpy functions and methods
        # however, there is an orientaiton difference between opencv and numpy
        fz = cv.Get2D(img,(defacing.imsize[1]-face_data.shape[2])/2 + features[m][1],(defacing.imsize[0]-face_data.shape[0])/2 + features[m][0])[0] +(face_data.shape[1]-kmax)
        fi = features[m][0]-(defacing.imsize[0]-face_data.shape[0])/2
        fj = features[m][1]-(defacing.imsize[1]-face_data.shape[1])/2

        print fi,fz,fj
        face_data_2[fi-dx/2:fi+dx/2,:,fj-dy/2:fj+dy/2] = 0
        #for i in range(-radius/2,radius/2):
        #	for j in range(-radius/2,radius/2):	
        #		for z in range(face_data.shape[1]):
        #			face_data[(fi+i)%face_data.shape[0],z,(fj+j)%face_data.shape[2]]=0

    #img_data2[img_data2<thres]=0	
    #vr.show(np.concatenate((face_data_2,img_data2,face_data_2+img_data2),axis=0),0)
        
    print '3'
    #cv.WaitKey(0)
    tmp = os.path.splitext(data)
    try:
        print "face max %f, img_max %f"%(face_data_2.max(),defaced_img.max())
        nim = NiftiImage(face_data_2+defaced_img)
        print "saving image"
        nim.save(tmp[0]+'_partially_defaced'+tmp[1])
        print 'success'
    except:
            raw_input("couldn't save file")



def saveInfo(data, jsuffix = ".json"):
    # to make a json tuple
    info_files = glob.glob(os.path.join(dirName,"*"+jsuffix))

    nim = NiftiImage(data)
    org_v = nim.voxdim
    
    minscale = min(org_v)
    scale_factor = org_v[0]/minscale, org_v[1]/minscale, org_v[2]/minscale
    
    if (inter_v == org_v):
        inter_done = True
    else:
        inter_doen = False
        inter_v = ndi.zoom(nim.data,scale_factor, output = nim.data.dtype)

    depth_mp = 0 #json
    
    f = open(jsuffix,'w')
    f.write("original voxel dimension: " + org_v +"\n interpolation done: " + inter_done
        +"\n interpolation scale factor: " + scale_factor+ "\n interpolated voxel dimension: " + inter_v
        + "\n depth map: " + depth_mp)
    
    
    # include all the left and right medial in here?		

def main():
    
    parser = getParser()
    (options, args) = parser.parse_args()
    
    if (options.command == 'd'):
        CallDefacer(options.filename)
    elif (options.command == 'e'):
        RemoveFeatures(options.filename,options.threshold,options.mode)
    elif (options.command == 'l'):
        LocateFeatures(options.filename,options.threshold,options.mode)
    elif (options.command == 's'):
        save_model_as_ply(options.filename , options.threshold , options.level)

	
if __name__ == '__main__':

    main()

